package com.kh.rationaldrugreview.dto;

import com.kh.rationaldrugreview.entity.KnowledgeEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 实体匹配结果
 * Entity Matching Result
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class EntityMatchResult {
    
    /**
     * 原始输入名称
     */
    private String originalName;
    
    /**
     * 匹配到的实体
     */
    private KnowledgeEntity matchedEntity;
    
    /**
     * 匹配的canonical名称
     */
    private String canonicalName;
    
    /**
     * 匹配的实体ID
     */
    private Long entityId;
    
    /**
     * 实体类型
     */
    private String entityType;
    
    /**
     * 匹配置信度（0-1）
     */
    private Double confidence;
    
    /**
     * 匹配类型
     */
    private MatchType matchType;
    
    /**
     * 匹配算法
     */
    private MatchAlgorithm algorithm;
    
    /**
     * 候选实体列表（当置信度不高时提供）
     */
    private List<CandidateEntity> candidates;
    
    /**
     * 匹配详情
     */
    private MatchDetails details;
    
    /**
     * 是否需要人工确认
     */
    private Boolean needsConfirmation;
    
    /**
     * 匹配耗时（毫秒）
     */
    private Long processingTimeMs;
    
    /**
     * 匹配时间
     */
    private LocalDateTime matchedAt;
    
    /**
     * 错误信息（如果匹配失败）
     */
    private String errorMessage;
    
    /**
     * 匹配类型枚举
     */
    public enum MatchType {
        EXACT("精确匹配"),
        NORMALIZED("标准化匹配"),
        ALIAS("别名匹配"),
        FUZZY("模糊匹配"),
        PHONETIC("拼音匹配"),
        LLM("LLM匹配"),
        PARTIAL("部分匹配"),
        NOT_FOUND("未找到");
        
        private final String description;
        
        MatchType(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }
    
    /**
     * 匹配算法枚举
     */
    public enum MatchAlgorithm {
        HASH_MAP("哈希表查找"),
        NORMALIZATION("名称标准化"),
        ALIAS_LOOKUP("别名查询"),
        LEVENSHTEIN("编辑距离"),
        JARO_WINKLER("Jaro-Winkler距离"),
        N_GRAM("N-gram相似度"),
        PINYIN("拼音匹配"),
        SOUNDEX("Soundex语音编码"),
        GPT_35("GPT-3.5"),
        GPT_4("GPT-4"),
        CLAUDE("Claude"),
        HYBRID("混合算法");
        
        private final String description;
        
        MatchAlgorithm(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }
    
    /**
     * 候选实体
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class CandidateEntity {
        private Long entityId;
        private String entityName;
        private String canonicalName;
        private String entityType;
        private Double similarity;
        private String matchReason;
        private Map<String, Object> attributes;
    }
    
    /**
     * 匹配详情
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class MatchDetails {
        /**
         * 相似度得分明细
         */
        private Map<String, Double> similarityScores;
        
        /**
         * 匹配步骤
         */
        private List<String> matchingSteps;
        
        /**
         * 标准化过程
         */
        private NormalizationProcess normalization;
        
        /**
         * LLM推理（如果使用）
         */
        private LLMReasoning llmReasoning;
        
        /**
         * 匹配规则
         */
        private List<String> appliedRules;
        
        /**
         * 缓存信息
         */
        private CacheInfo cacheInfo;
    }
    
    /**
     * 标准化过程
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class NormalizationProcess {
        private String originalInput;
        private String afterTrim;
        private String afterCaseConversion;
        private String afterPunctuationRemoval;
        private String afterDosageFormRemoval;
        private String finalNormalized;
        private List<String> removedParts;
    }
    
    /**
     * LLM推理信息
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class LLMReasoning {
        private String model;
        private String prompt;
        private String response;
        private Integer tokensUsed;
        private Long responseTimeMs;
        private String reasoning;
    }
    
    /**
     * 缓存信息
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class CacheInfo {
        private Boolean cacheHit;
        private String cacheKey;
        private LocalDateTime cachedAt;
        private Long ttlSeconds;
    }
    
    /**
     * 判断是否匹配成功
     */
    public boolean isMatched() {
        return matchedEntity != null && confidence != null && confidence > 0;
    }
    
    /**
     * 判断是否高置信度匹配
     */
    public boolean isHighConfidence() {
        return confidence != null && confidence >= 0.85;
    }
    
    /**
     * 判断是否中等置信度匹配
     */
    public boolean isMediumConfidence() {
        return confidence != null && confidence >= 0.70 && confidence < 0.85;
    }
    
    /**
     * 判断是否低置信度匹配
     */
    public boolean isLowConfidence() {
        return confidence != null && confidence < 0.70;
    }
    
    /**
     * 获取最佳候选实体
     */
    public CandidateEntity getBestCandidate() {
        if (candidates == null || candidates.isEmpty()) {
            return null;
        }
        return candidates.stream()
            .max((c1, c2) -> Double.compare(
                c1.getSimilarity() != null ? c1.getSimilarity() : 0,
                c2.getSimilarity() != null ? c2.getSimilarity() : 0
            ))
            .orElse(null);
    }
    
    /**
     * 创建未匹配结果
     */
    public static EntityMatchResult notFound(String originalName, String entityType) {
        return EntityMatchResult.builder()
            .originalName(originalName)
            .entityType(entityType)
            .matchType(MatchType.NOT_FOUND)
            .confidence(0.0)
            .needsConfirmation(true)
            .matchedAt(LocalDateTime.now())
            .build();
    }
    
    /**
     * 创建精确匹配结果
     */
    public static EntityMatchResult exactMatch(String originalName, KnowledgeEntity entity) {
        return EntityMatchResult.builder()
            .originalName(originalName)
            .matchedEntity(entity)
            .canonicalName(entity.getCanonicalName())
            .entityId(entity.getEntityId())
            .entityType(entity.getEntityType())
            .matchType(MatchType.EXACT)
            .algorithm(MatchAlgorithm.HASH_MAP)
            .confidence(1.0)
            .needsConfirmation(false)
            .matchedAt(LocalDateTime.now())
            .build();
    }
}